#include "idcardocr.h"
#include "common.h"
#include "inifile.h"

#define DG0 0x00000001
#define DG1 0x00000002
#define DG2 0x00000004
#define DG3 0x00000008
#define DG4 0x00000010
#define DG5 0x00000020
#define DG6 0x00000040
#define DG7 0x00000080
#define DG8 0x00000100
#define DG9 0x00000200
#define DG10 0x00000400
#define DG11 0x00000800
#define DG12 0x00001000
#define DG13 0x00002000
#define DG14 0x00004000
#define DG15 0x00008000
#define DG16 0x00010000
#define DG17 0x00020000

#define WHITEIMAGE 0x00000001
#define IRIMAGE 0x00000002
#define UVIMAGE 0x00000004
#define PAGEHEAD 0x00000008
#define CHIPHEAD 0x00000010

int (WINAPI *pInitIDCard)(LPCTSTR lpUserID, int nType,LPCTSTR lpDirectory);
void (WINAPI *pFreeIDCard)();
int (WINAPI *pAcquireImage)(int nImageSizeType);
int (WINAPI *pGetRecogResult)(int nIndex, LPTSTR lpBuffer,int &nBufferLen);
int (WINAPI *pGetFieldName)(int nIndex, LPTSTR lpBuffer,int &nBufferLen);
int (WINAPI *pSetIDCardID)(int nMainID,int nSubID[],int nSubIdCount);
int (WINAPI *pAddIDCardID)(int nMainID,int nSubID[],int nSubIdCount);
int (WINAPI *pSetIOStatus)(int,bool);
int (WINAPI *pGetGrabSignalType)();
bool (WINAPI *pGetVersionInfo)(LPCTSTR lpBuffer,int nBufferLen);
BOOL (WINAPI *pGetVersionInfoKernal)(LPCTSTR lpBuffer,int nBufferLen);
BOOL (WINAPI *pCheckDeviceOnline)();
BOOL (WINAPI *pGetCurrentDevice)(LPTSTR deviceName, int nBufferLenth);
int (WINAPI *pGetDeviceSN)(LPTSTR ,int );
int (WINAPI *pUTF8CharToWChar)(wchar_t* pwszDest, const char* pszSrc, int nWcharLen);
int (WINAPI *pWCharToUTF8Char)(char* pszDest,const wchar_t* pwszSrc,int nCharLen);
int (WINAPI *pClassifyIDCard)(int& nCardType);				// 对识别的证件自动分类
int (WINAPI *pRecogChipCard)(int nDGGroup,bool bRecogVIZ,int nSaveImageType);	// 采集图并识别带电子芯片的证件
int (WINAPI *pRecogGeneralMRZCard)(bool bRecogVIZ,int nSaveImageType);			// 采集图像并根据模板识别带有MRZ的证件
int (WINAPI *pRecogCommonCard)(int nSaveImageType);			// 采集图像并对指定类型的证件进行识别
int (WINAPI *pSaveImageEx)(LPCTSTR lpFileName,int nType);
int (WINAPI *pGetDataGroupContent)(int nDGIndex,bool bRawData,unsigned char * lpBuffer,int &len);	// 获取从芯片中读取到的DG的信息

#define QStringToTCHAR(x) (wchar_t*) x.utf16()
QString strUserID = "48267961297902416835";   //用户ID
int nCardType;       // 证件类型
IdCardOcr::IdCardOcr(QObject *parent):QThread(parent)
{
    m_bInitSuccess = false;
    m_bStop = false;
    m_bVIZ = false;
    m_SaveImageFlag = 0;
    m_nCardType = 0;
    m_nIDNum = CCommon::Instance()->GetIniFilePtr()->GetOcrCfg().nCardType;
}

IdCardOcr::~IdCardOcr()
{
    m_bStop = true;
    quit();
    wait();
}

void IdCardOcr::GetRecogCondition()
{
    //获取识别约束条件
    m_ReadDGFlag |= DG1;
    m_ReadDGFlag |= DG2;
    m_ReadDGFlag |= DG11;
    m_ReadDGFlag |= DG12;

    m_SaveImageFlag |= WHITEIMAGE;
  //  m_SaveImageFlag |= IRIMAGE;
    m_SaveImageFlag |= PAGEHEAD;
    m_bVIZ = false;
}

void IdCardOcr::GetContent()
{
    int nRet = 0;
    const int MAX_CH_NUM = 256;
    TCHAR szFieldValue[MAX_CH_NUM] = {0};
    TCHAR szFieldName[MAX_CH_NUM] = {0};
    int nBufLen = MAX_CH_NUM*sizeof(TCHAR);
    int nIndex = 0;

    while(1)
    {
        nBufLen = MAX_CH_NUM*sizeof(TCHAR);
        memset(szFieldValue,0,nBufLen);
        memset(szFieldName,0,nBufLen);

        nRet = pGetRecogResult(nIndex, szFieldValue, nBufLen);
        if(3 == nRet)
        {
            break;
        }

        nBufLen = MAX_CH_NUM*sizeof(TCHAR);
        pGetFieldName(nIndex, szFieldName, nBufLen);

        QString strName = QString::fromWCharArray(szFieldName);
        QString strValue = QString::fromWCharArray(szFieldValue);

        if(strName == "姓名")
        {
            m_stInfo.strName = strValue;
        }
        else if(strName == "性别")
        {
            m_stInfo.strSex = strValue;
        }
        else if(strName == "民族")
        {
            m_stInfo.strNation = strValue;
        }
        else if(strName == "出生")
        {
            m_stInfo.strBirthday = strValue;
        }
        else if(strName == "住址")
        {
            m_stInfo.strAddress = strValue;
        }
        else if(strName == "公民身份号码")
        {
            m_stInfo.strIDCode = strValue;

            QString strFile = CCommon::Instance()->strAppDir + "/idcardocrHead.jpg";
            QPixmap pix;
            bool bLoad = pix.load(strFile, ".jpg");
            emit sigIdcardInfo(m_stInfo, pix);
        }
        else if(strName == "签发机关")
        {
            m_stInfo.strDepartment = strValue;
        }
        else if(strName == "有效日期")
        {
            m_stInfo.strValideDate = strValue;
        }

        nIndex++;
    }
}

int IdCardOcr::InitCardDll()
{
    if(m_bInitSuccess)
    {
        return 0;
    }

    m_hIDCard = LoadLibrary(L"IDCard.dll");
    if(NULL == m_hIDCard)
        return 1001;

    pInitIDCard = (int (WINAPI*)(LPCTSTR, int,LPCTSTR))GetProcAddress(m_hIDCard,LPCSTR("InitIDCard"));
    pFreeIDCard=(void (WINAPI *)())GetProcAddress(m_hIDCard,LPCSTR("FreeIDCard"));
    pAcquireImage=(int (WINAPI *)(int))GetProcAddress(m_hIDCard,LPCSTR("AcquireImage"));
    pGetRecogResult=(int (WINAPI *)(int, LPTSTR,int&))GetProcAddress(m_hIDCard,LPCSTR("GetRecogResult"));
    pGetFieldName=(int (WINAPI *)(int, LPTSTR,int&))GetProcAddress(m_hIDCard,LPCSTR("GetFieldName"));
    pSetIDCardID = (int (WINAPI *)(int ,int *,int ))GetProcAddress(m_hIDCard, LPCSTR("SetIDCardID"));
    pAddIDCardID = (int (WINAPI *)(int ,int *,int ))GetProcAddress(m_hIDCard, LPCSTR("AddIDCardID"));
    pSetIOStatus = (int (WINAPI * )(int,bool))GetProcAddress(m_hIDCard, LPCSTR("SetIOStatus"));
    pGetGrabSignalType = (int (WINAPI *)())GetProcAddress(m_hIDCard, LPCSTR("GetGrabSignalType"));
    pGetVersionInfo = (bool (WINAPI *)(LPCTSTR,int))GetProcAddress(m_hIDCard,LPCSTR("GetVersionInfo"));
    pGetVersionInfoKernal = (BOOL (WINAPI *)(LPCTSTR,int))GetProcAddress(m_hIDCard,LPCSTR("GetVersionInfoKernal"));
    pCheckDeviceOnline = (BOOL (WINAPI *)())GetProcAddress(m_hIDCard,LPCSTR("CheckDeviceOnline"));
    pGetCurrentDevice = (BOOL (WINAPI *)(LPTSTR,int))GetProcAddress(m_hIDCard,LPCSTR("GetCurrentDevice"));
    pGetDeviceSN = (int (WINAPI *)(LPTSTR,int))GetProcAddress(m_hIDCard,LPCSTR("GetDeviceSN"));
    pUTF8CharToWChar = (int (WINAPI *)(wchar_t*,const char*,int))GetProcAddress(m_hIDCard,LPCSTR("UTF8CharToWChar"));
    pWCharToUTF8Char = (int (WINAPI *)(char*,const wchar_t*,int))GetProcAddress(m_hIDCard,LPCSTR("WCharToUTF8Char"));
    pClassifyIDCard = (int (WINAPI*)(int&))GetProcAddress(m_hIDCard, LPCSTR("ClassifyIDCard"));
    pRecogChipCard = (int (WINAPI*)(int,bool,int))GetProcAddress(m_hIDCard,LPCSTR("RecogChipCard"));
    pRecogGeneralMRZCard = (int (WINAPI*)(bool,int))GetProcAddress(m_hIDCard,LPCSTR("RecogGeneralMRZCard"));
    pRecogCommonCard = (int (WINAPI*)(int))GetProcAddress(m_hIDCard,LPCSTR("RecogCommonCard"));
    pSaveImageEx = (int (WINAPI*)(LPCTSTR,int))GetProcAddress(m_hIDCard,LPCSTR("SaveImageEx"));
    pGetDataGroupContent = (int (WINAPI*)(int,bool,unsigned char*,int&))GetProcAddress(m_hIDCard,LPCSTR("GetDataGroupContent"));

    if(NULL == pInitIDCard ||
       NULL == pFreeIDCard ||
        NULL == pAcquireImage ||
        NULL == pGetRecogResult||
        NULL == pGetFieldName ||
        NULL == pSetIDCardID ||
        NULL == pAddIDCardID ||
        NULL == pSetIOStatus ||
        NULL == pGetGrabSignalType ||
        NULL == pGetVersionInfo ||
        NULL == pGetVersionInfoKernal||
        NULL == pCheckDeviceOnline ||
        NULL == pGetCurrentDevice ||
        NULL == pGetDeviceSN||
        NULL == pUTF8CharToWChar ||
        NULL == pWCharToUTF8Char||
        NULL == pClassifyIDCard ||
        NULL == pRecogChipCard  ||
        NULL == pRecogGeneralMRZCard ||
        NULL == pRecogCommonCard ||
        NULL == pSaveImageEx ||
        NULL == pGetDataGroupContent)
    {
        m_bInitSuccess = false;
        FreeLibrary(m_hIDCard);
        m_hIDCard = NULL;
        return 1002;
    }
    else
    {
        int nRet = pInitIDCard(QStringToTCHAR(strUserID),0,NULL);
        if(0 != nRet)
        {
            FreeCardDll();
            return nRet;
        }

        m_bInitSuccess = true;
        return 0;
    }
}

void IdCardOcr::FreeCardDll()
{
    if (NULL != pFreeIDCard)
    {
        pFreeIDCard();
    }

    if(NULL != m_hIDCard)
    {
        FreeLibrary(m_hIDCard);
    }

    m_hIDCard = NULL;
    m_bInitSuccess = false;
    pInitIDCard = NULL;
    pFreeIDCard = NULL;
    pAcquireImage = NULL;
    pGetRecogResult = NULL;
    pGetFieldName = NULL;
    pSetIDCardID = NULL;
    pAddIDCardID = NULL;
    pSetIOStatus = NULL;
    pGetGrabSignalType = NULL;
    pGetVersionInfo = NULL;
    pGetVersionInfoKernal = NULL;
    pCheckDeviceOnline = NULL;
    pGetCurrentDevice = NULL;
    pGetDeviceSN = NULL;
    pUTF8CharToWChar = NULL;
    pWCharToUTF8Char = NULL;

    pClassifyIDCard = NULL;
    pRecogChipCard = NULL;
    pRecogGeneralMRZCard = NULL;
    pRecogCommonCard = NULL;
    pSaveImageEx = NULL;
    pGetDataGroupContent = NULL;

//    m_bWhiteImage = false;
//    m_bIRImage = false;
//    m_bUVImage = false;
//    m_bPageHead = false;
//    m_bChipHead = false;
//    m_bVIZ = false;
//    for(int i=0;i<18;i++)
//        m_bDG[i] = false;
//    m_OldRect.SetRect(0,0,0,0);
//    m_ctrlInfo.RemoveAll();
//    m_nCardType = 0;
//    m_nMainID = 0;
//    m_strErrMsg = _T("");
//    m_strWorkPath = _T("");
    //    m_strImagePath = _T("");
}

void IdCardOcr::ReadCard()
{
    int nRet = 0;
    GetRecogCondition();

    if(1 == m_nCardType)
    {
//        nRet = pRecogChipCard(m_ReadDGFlag,m_bVIZ,m_SaveImageFlag);
//        if(nRet == m_nMainID)
//        {
//            m_strResult = _T("Success to read the card\r\n");
//            m_strDGResult = _T("Success to read the card\r\n");
//            GetContent();
//            GetDGContent();
//        }
//        else
//        {
//            m_strResult = _T("fail to read the card\r\n");
//            m_strDGResult = _T("fail to read the card\r\n");
//        }
    }
    else if(2 == m_nCardType)
    {
//        nRet = pRecogGeneralMRZCard(m_bVIZ,m_SaveImageFlag);
//        if(nRet == m_nMainID)
//        {
//            m_strResult = _T("Success to recognize the card\r\n");
//            GetContent();
//        }
//        else
//            m_strResult = _T("fail to recognize the card\r\n");
    }
    else if(3 == m_nCardType)
    {//常用证件
        nRet = pRecogCommonCard(m_SaveImageFlag);
        if(nRet == m_nMainID)
        {
            GetContent();
        }
        else
        {
            //m_strResult = _T("fail to recognize the card\r\n");
        }

    }
    QString strFileName = CCommon::Instance()->strAppDir + "/idcardocr.jpg";
    pSaveImageEx(strFileName.toStdWString().c_str(),m_SaveImageFlag);
}

void IdCardOcr::run()
{
    while(!m_bStop)
    {
        if(InitCardDll() == 0)
        {
            while(!m_bStop)
            {
                int nSubID[1] = {0};
                pSetIDCardID(m_nIDNum,nSubID,1);
                m_nMainID = pClassifyIDCard(m_nCardType);
                ReadCard();

                m_bStop = true;
                break;
            }
        }

        QThread::msleep(1);
    }

    qDebug("IdCardOcr thread exit normal.\n");
}
